

#include "user_struct.h"
#include "dma.h"
#include "uart_comm_ex_api.h"
#include "uart_comm_frame.h"
#include "uart_comm_struct.h"
#include "systick.h"
#include "power_ctrl.h"
#include "sd2059.h"
#include "BMS_can_msg.h"
#include "fault_analyse.h"
#include "clean_can_msg.h"

// Naviagtion send to MCU frame & data struct
STR_COMM_TIME_SET   dataTimeSet;
STR_COMM_FRAME      cmdframTimeSet;   

STR_COMM_P_OFF_TYPE powerOffSet;
STR_COMM_FRAME      cmdframePowerOff;

STR_COMM_SHIELD     breakShield;
STR_COMM_FRAME      cmdframeBreakShield;

STR_COMM_LED_BUZZER ledBuzzerSet;
STR_COMM_FRAME      cmdframeLedBuzzerSet;

STR_UOLOAD_RTC_TIME dataRTCTimeSet;
STR_COMM_FRAME      cmdRTCTImeSet;

STR_COMM_HEARTBEAT  heartbeatSet;
STR_COMM_FRAME      cmdHeartbeat;


STR_COMM_CLE_CTRL   cleanCtrlSet;
STR_COMM_FRAME      cmdCleanCtrl;


STR_COMM_FRAME *cmdframGroup[CMD_FRAM_ALL] = {  &cmdframTimeSet, 
												&cmdframePowerOff, 
												&cmdframeBreakShield,
												&cmdframeLedBuzzerSet,
												&cmdRTCTImeSet,
												&cmdHeartbeat, 
												&cmdCleanCtrl};

												
// Naviagtion send to MCU frame & data struct
STR_UPLOAD_CHARGE      dataChargePos;
STR_COMM_FRAME         uploadChargePos;

STR_UPLOAD_IO_SIGNAL   dataIOSignal;
STR_COMM_FRAME         uploadIOSignal;

STR_UPLOAD_CLIFF       dataCliff;
STR_COMM_FRAME         uploadCliff;

STR_UPLOAD_ULTRASOUND  dataUltrasound;
STR_COMM_FRAME         uploadUltrasound;

STR_UPLOAD_P_OFF_REQ   dataPowerOffReq;
STR_COMM_FRAME         uploadPowerOffReq;

STR_UOLOAD_CHARGE_FSM  dataChargeFSM;
STR_COMM_FRAME         uploadChargeFSM;

STR_UOLOAD_RTC_TIME    dataRTCTime;
STR_COMM_FRAME		   uploadRTCTime;

STR_UOLOAD_VOT_CUR     dataVotCur;
STR_COMM_FRAME         uploadVotCur;


STR_UPLOAD_CLE_STATUS  dataCleanStatus;
STR_COMM_FRAME         uploadCleanStatus;

STR_UPLOAD_CLE_SENSOR  dataCleanSensor;
STR_COMM_FRAME         uploadCleanSensor;


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void cmd_frame_set(STR_COMM_FRAME *frameHdl, uint16_t Len, uint8_t *databuf)
{
	frameHdl->length_H = (((LEGTH_CMD_ID + Len) >> 8) & 0x00FF);
	frameHdl->length_L = (((LEGTH_CMD_ID + Len) >> 0) & 0x00FF);
	frameHdl->databuf = databuf;	
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void upload_frame_set(STR_COMM_FRAME *frameHdl, uint16_t ID, uint16_t Len, uint8_t *databuf)
{
	frameHdl->head_H = FRAME_HEAD_H;
	frameHdl->head_L = FRAME_HEAD_L;
	
	frameHdl->cmd_ID_H = ((ID >> 8) & 0x00FF);
	frameHdl->cmd_ID_L = ((ID >> 0) & 0x00FF);	
	
	frameHdl->length_H = (((LEGTH_CMD_ID + Len) >> 8) & 0x00FF);
	frameHdl->length_L = (((LEGTH_CMD_ID + Len) >> 0) & 0x00FF);
	
	frameHdl->databuf  = databuf;
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
void nav_comm_frame_init(void)
{
	cmd_frame_set(&cmdframTimeSet, DATA_LEGTH_TIME_SET, &dataTimeSet.data[0]);
	
	cmd_frame_set(&cmdframePowerOff, DATA_LEGTH_P_OFF_TYPE, &powerOffSet.data);
	
	cmd_frame_set(&cmdframeBreakShield, DATA_LEGTH_BREAK_SHIELD, &breakShield.data[0]);
	
	cmd_frame_set(&cmdframeLedBuzzerSet, DATA_LEGTH_LED_BUZZER, &ledBuzzerSet.data[0]);	
	
	cmd_frame_set(&cmdRTCTImeSet, DATA_LEGTH_RTC_TIME, &dataRTCTimeSet.data[0]);	
	
	cmd_frame_set(&cmdHeartbeat, DATA_LEGTH_HEARTBEAT, &heartbeatSet.data[0]);	
	
	cmd_frame_set(&cmdCleanCtrl, DATA_LEGTH_CLEAN_CTRL, &cleanCtrlSet.data[0]);
	
	
	upload_frame_set(&uploadChargePos, ID_CHARGE_POS_UPLOAD, DATA_LEGTH_CHARGE_POS, &dataChargePos.data[0]);
	
	upload_frame_set(&uploadIOSignal, ID_IO_SIGNAL_UPLOAD, DATA_LEGTH_IO_SIGNAL, &dataIOSignal.data[0]);	

	upload_frame_set(&uploadCliff, ID_CLIFF_UPLOAD, DATA_LEGTH_CLIFF, &dataCliff.data[0]);
	
	upload_frame_set(&uploadUltrasound, ID_ULTRASOUND_UPLOAD, DATA_LEGTH_ULTRASOUMD, &dataUltrasound.data[0]);
	
	upload_frame_set(&uploadPowerOffReq, ID_P_OFF_REQ_UPLOAD, DATA_LEGTH_P_OFF_REQ, &dataPowerOffReq.data[0]);
	
	upload_frame_set(&uploadChargeFSM, ID_CHARGE_FSM_UPLOAD, DATA_LEGTH_CHARGE_FSM, &dataChargeFSM.data[0]);

	upload_frame_set(&uploadRTCTime, ID_RCT_TIME_UPLOAD, DATA_LEGTH_RTC_TIME, &dataRTCTime.data[0]);

	upload_frame_set(&uploadVotCur, ID_VOT_CUR_UPLPAD, DATA_LEGTH_VOT_CUR, &dataVotCur.data[0]);
	
	upload_frame_set(&uploadCleanStatus, ID_CLE_STATUS_UPLOAD, DATA_LEGTH_CLE_STATUS, &dataCleanStatus.data[0]);
	
	upload_frame_set(&uploadCleanSensor, ID_CLE_SENSOR_UPLOAD, DATA_LEGTH_CLE_SENSOR, &dataCleanSensor.data[0]);
		
}



/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
uint8_t comm_frame_handle(STR_COMM_FRAME *frame, uint8_t *databuf, uint8_t ack)
{
	uint16_t store_length = 0;

	store_length = comm_frame_store(frame, databuf);

	if((store_length != 0) && (ack == 1))
	{
		comm_frame_upload(frame, &commUARTSendbuf);	
	}

	return store_length;
}


/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/
uint8_t comm_frame_analysis(STR_COMM_FRAME *frame[], STR_RINGBUF* bufhdl)	
{

	static uint8_t  databuf[COMM_BUFF_NUM];
	uint16_t length;
	uint16_t cmdId = 0;
	uint16_t store_length = 0;
	uint8_t  rece_cnt = 0;
	
	length = ringBufRead(bufhdl, (char*)databuf, COMM_BUFF_NUM);
	
	for(uint16_t i=0;i<length;i++)
	{
		if((databuf[i] == FRAME_HEAD_H) && (databuf[i+1] == FRAME_HEAD_L))
		{
			store_length = 0;
			cmdId = (databuf[i+6] + (databuf[i+7] << 8));
			
 			switch(cmdId)
			{
				case ID_CMD_TIME_SET:
					store_length = comm_frame_handle(frame[CMD_TIME_SET], &databuf[i], 0);
					if(store_length != 0)
					{	
						volatile uint64_t synchro_time = 0;		
						dataTimeSet.real.time = i64_LSB_to_MSB(dataTimeSet.real.time);
						synchro_time = (uint64_t)(dataTimeSet.real.time) / 1000;
						set_system_runingtime(synchro_time);
					}
					
				break;
										
				
				case ID_CMD_LED_BUZZER:
				{
					
					store_length = comm_frame_handle(frame[CMD_LED_BUZZER], &databuf[i], 1);
					
					if(store_length != 0)
					{
						userHdl.ctrl.en_turn_left   = ledBuzzerSet.real.turn_left;
						userHdl.ctrl.en_turn_right  = ledBuzzerSet.real.turn_right;
						userHdl.ctrl.type_LED_left  = ledBuzzerSet.real.LED_left;
						userHdl.ctrl.type_LED_right = ledBuzzerSet.real.LED_right;
						userHdl.ctrl.en_buzzer_x1   = ledBuzzerSet.real.buzzerX1;
						userHdl.ctrl.en_buzzer_x1   = ledBuzzerSet.real.buzzerX2;
					}
					
					break;
				}
				
				
				case ID_CMD_HEARTBEAT:
				{
					store_length = comm_frame_handle(frame[CMD_HEARTBEAT], &databuf[i], 0);
					
					if(store_length != 0)
					{
						reset_comm_loss_time(ENUM_NAV);
					}

					break;
				}
				
					
				default:
				break;					
					
			}
			
			if(store_length != 0)   rece_cnt++;
			i = i + store_length;
		}
	}

	return rece_cnt;
}



/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void upload_uartcomm_data(uint16_t cmd_id)
{
	#if 0
	switch(cmd_id)
	{
		case ID_CHARGE_POS_UPLOAD:
			
			
			dataChargePos.real.time = (uint16_t)get_system_runingtime();
			dataChargePos.real.chargeSignal[0] = userHdl.signal.chargeSignal[NUM_INFRARED_BACK_LEFT];
			dataChargePos.real.chargeSignal[1] = userHdl.signal.chargeSignal[NUM_INFRARED_BACK_RIGHT];
			dataChargePos.real.chargeSignal[2] = userHdl.signal.chargeSignal[NUM_INFRARED_LEFT];
			dataChargePos.real.chargeSignal[3] = userHdl.signal.chargeSignal[NUM_INFRARED_RIGHT];
		
			comm_frame_upload(&uploadChargePos, &commUARTSendbuf);
		
			break;
		
		
		case ID_BUMPER_UPLOAD:
		case ID_IO_SIGNAL_UPLOAD:
			
			dataIOSignal.real.time = (uint16_t)get_system_runingtime();
			dataIOSignal.real.bumper[0] = userHdl.signal.bumper[0];
			dataIOSignal.real.bumper[1] = userHdl.signal.bumper[1];
			dataIOSignal.real.break_key  = userHdl.signal.break_key;
			dataIOSignal.real.break_sort = userHdl.signal.break_sort;
			dataIOSignal.real.key_power  = userHdl.signal.power_key;
			dataIOSignal.real.key_start  = userHdl.signal.start_key;
		
			comm_frame_upload(&uploadIOSignal, &commUARTSendbuf);
		
			break;
		
		
		case ID_CLIFF_UPLOAD:
			
			dataCliff.real.time = (uint16_t)get_system_runingtime();
			dataCliff.real.cliff[0] = userHdl.signal.cliff_flg[0];
			dataCliff.real.cliff[1] = userHdl.signal.cliff_flg[1];
			dataCliff.real.cliff[2] = userHdl.signal.cliff_flg[2];
			dataCliff.real.cliff[3] = userHdl.signal.cliff_flg[3];
			dataCliff.real.cliff[4] = userHdl.signal.cliff_flg[4];
			dataCliff.real.cliff[5] = userHdl.signal.cliff_flg[5];
			
			comm_frame_upload(&uploadCliff, &commUARTSendbuf);
		
			break;
		
		
		case ID_CHARGE_FSM_UPLOAD:
			
			dataChargeFSM.real.time = (uint16_t)get_system_runingtime();
			dataChargeFSM.real.charge_FSM = userHdl.signal.charge_clean + userHdl.signal.charge_service;
			dataChargeFSM.real.battery_level = bmsStatus.raw.bit.soc + serBmsStatus.soc;
		
			comm_frame_upload(&uploadChargeFSM, &commUARTSendbuf);
		
		case ID_RCT_TIME_UPLOAD:
			
			dataRTCTime.real.second = RTC_realtime.type.second;
			dataRTCTime.real.minute = RTC_realtime.type.minute;
			dataRTCTime.real.week = RTC_realtime.type.week;
			dataRTCTime.real.hour = RTC_realtime.type.hour;
			dataRTCTime.real.day = RTC_realtime.type.day;
			dataRTCTime.real.month = RTC_realtime.type.month;
			dataRTCTime.real.year = RTC_realtime.type.year;
			dataRTCTime.real.reserve = 0;
			
			comm_frame_upload(&uploadRTCTime, &commUARTSendbuf);
		
			break;
		
		case ID_VOT_CUR_UPLPAD:
			
			dataVotCur.real.vdc = (uint16_t)userHdl.signal.real.vdc * 10.0f;
			dataVotCur.real.idc = (uint16_t)userHdl.signal.real.idc * 10.0f;
			dataVotCur.real.vdc_realy = (uint16_t)userHdl.signal.real.vdc_motor * 10.0f;
			dataVotCur.real.idc_motor = (uint16_t)userHdl.signal.real.idc_motor * 10.0f;
			dataVotCur.real.idc_ctrl = (uint16_t)userHdl.signal.real.idc_clean * 10.0f;
			dataVotCur.real.idc_service = (uint16_t)userHdl.signal.real.idc_service * 10.0f;
		
			comm_frame_upload(&uploadVotCur, &commUARTSendbuf);
		
			break;	

		case ID_CLE_STATUS_UPLOAD:
			
			dataCleanStatus.real.brush_FSM = cleanMsgRec.status.brush_FSM;
			dataCleanStatus.real.dustfan_FSM = cleanMsgRec.status.dusfan_FSM;
			dataCleanStatus.real.brush_lift_FSM = cleanMsgRec.status.brush_lift_FSM;
			dataCleanStatus.real.water_lift_FSM = cleanMsgRec.status.water_lift_FSM;
			dataCleanStatus.real.brush_right_FSM = cleanMsgRec.status.brush_right_FSM;
		
			comm_frame_upload(&uploadCleanStatus, &commUARTSendbuf);
		
			break;
		
		
		case ID_CLE_SENSOR_UPLOAD:
			
			dataCleanSensor.real.waste_empty = cleanMsgRec.sensor.waste_empty;
			dataCleanSensor.real.waste_full = cleanMsgRec.sensor.waste_full;
			dataCleanSensor.real.water_full = cleanMsgRec.sensor.water_full;
			dataCleanSensor.real.water_level = cleanMsgRec.sensor.water_level;
			dataCleanSensor.real.sink_full = cleanMsgRec.sensor.sink_full;
			dataCleanSensor.real.agent_level = cleanMsgRec.sensor.agent_level;

			comm_frame_upload(&uploadCleanSensor, &commUARTSendbuf);
		
			break;
		
		default:
			break;
	}
	#endif
}	



/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void upload_ultrasound_data(uint16_t ultra_ID, uint16_t dis_mm)
{
	dataUltrasound.real.time = (uint16_t)get_system_runingtime();
	dataUltrasound.real.ID = ultra_ID;
	dataUltrasound.real.distance_mm = dis_mm;
	
	comm_frame_upload(&uploadUltrasound, &commUARTSendbuf);
}



/*!
    \brief      
    \param[in]  none
    \param[out] none
    \retval     none
*/

void upload_poweroff_request(uint16_t cnt_down)
{
	dataPowerOffReq.real.time = (uint16_t)get_system_runingtime();
	dataPowerOffReq.real.cnt_down_ms = cnt_down;
	
	comm_frame_upload(&uploadPowerOffReq, &commUARTSendbuf);
}








